﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using nGSO.Config;
using nGSO.Performance;
using System.Reflection;

namespace nGSO.Tests
{
    [TestFixture]
    public class PefDataGenerator
    {
        private static PerfManager perfTracker = new Performance.PerfManager();

        public PefDataGenerator()
        {
            
        }

        [Test]
        public void ClearDb()
        {
            PerfDatabase.ClearAllResults();
        }

        [Test]
        public void GeneratePerfDataAgentFunction_Rastrigin_J2(
            [Values(3)] int perCaseTests,
            //[Values(25, 100, 500, 1000)]int population,
            [Values(1000)]int population,
            //[Values(150, 250, 500)]int iterations,
            [Values(500)]int iterations,
            [Values(true, false)] bool gsov1,
            [Values(true, false)] bool gsov2,
            [Values(2, 3, 5)] int desigredNoOfNeighbours,
            [Values(0.75, 1 , 1.5, 1.75)] double neighbourgoodRange
            )
        {
            GenerateTestData(perCaseTests, population, iterations, gsov1, gsov2, desigredNoOfNeighbours, neighbourgoodRange, "AgentFunction_Rastrigin_J2");
        }

        [Test]
        public void GeneratePerfDataAgentFunction_Himmelblau_J8(
           [Values(3)] int perCaseTests,
            //[Values(25, 100, 500, 1000)]int population,
            [Values(1000)]int population,
            //[Values(150, 250, 500)]int iterations,
            [Values(500)]int iterations,
            [Values(true, false)] bool gsov1,
            [Values(true, false)] bool gsov2,
            [Values(2, 3, 5)] int desigredNoOfNeighbours,
            [Values(0.75, 1, 1.5, 1.75)] double neighbourgoodRange
            )
        {
            GenerateTestData(perCaseTests, population, iterations, gsov1, gsov2, desigredNoOfNeighbours, neighbourgoodRange, "AgentFunction_Himmelblau_J8");
        }

        [Test]
        public void GeneratePerfDataAgentFunction_Peaks_J1(
            [Values(3)] int perCaseTests,
            //[Values(25, 100, 500, 1000)]int population,
            [Values(1000)]int population,
            //[Values(150, 250, 500)]int iterations,
            [Values(500)]int iterations,
            [Values(true, false)] bool gsov1,
            [Values(true, false)] bool gsov2,
            [Values(2, 3, 5)] int desigredNoOfNeighbours,
            [Values(0.75, 1, 1.5, 1.75)] double neighbourgoodRange
            )
        {
            GenerateTestData(perCaseTests, population, iterations, gsov1, gsov2, desigredNoOfNeighbours, neighbourgoodRange, "AgentFunction_Peaks_J1");
        }


        private static void GenerateTestData(int perCaseTests, int population, int iterations, bool gsov1, bool gsov2, int desigredNoOfNeighbours, double neighbourgoodRange, string caseName)
        {
            DateTime now = DateTime.Now;

            for (int i = 0; i < perCaseTests; i++)
            {
                if (gsov2 && !gsov1) // gsov1 should be enabled if gsov2 is on
                    return;

                Console.WriteLine("Funkcja: " + caseName + " Population: " + population + " iterations: " + iterations + " gsov1: " + gsov1 + " gsov2: "
                    + gsov2 + " desigred neighbours: " + desigredNoOfNeighbours + " neighbourgoodRange: " + neighbourgoodRange);

                GsoConfig config = new GsoConfig();
                config.SelectedOptimizationTask = OptimizationTaskConfig.Tasks.Single(s => s.Key == caseName).Value;
                config.CompileFitnessEvaluator();
                config.Population = population;
                config.MaxIterations = iterations;
                config.DesiredNoOfNeighbors = desigredNoOfNeighbours;
                config.RadialSensorRange = neighbourgoodRange;

                //config.SetOptimizationTaskParameters();

                if (gsov1)
                {
                    ExtendedAgentJump randomJumpGsoV1 = new ExtendedAgentJump() { Enabled = true };
                    config.AfterAgentMoveExtensions.Add(randomJumpGsoV1);

                    if (gsov2)
                    {
                        NeighborhoodRangeExtender rangeExtenderGsoV2 = new NeighborhoodRangeExtender() { Enabled = true };
                        config.AfterAgentMoveExtensions.Add(rangeExtenderGsoV2);
                    }
                }

                var test = perfTracker.StartTest(config);

                GsoEngine engine = new GsoEngine(config);
                var result = engine.StartGSOSolving();

                perfTracker.AddResult(test, result, config);
            }
        }
        

    }
}
